﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Codemi.Common.Interfaces;
using Codemi.Common.Helpers;
using Codemi.Common.Interfaces.Objects;
using Codemi.Common.Enums;

namespace Codemi.Common.Managers
{
    public class UsersManager
    {
        private UsersManager(IUserProvider userProvider)
        {
            this.userProvider = userProvider;
        }

        private static UsersManager instance;
        public static UsersManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new UsersManager(BootStraper.Initialize<IUserProvider>());
                }
                return instance;
            }
        }

        private IUserProvider userProvider { get; set; }
        

        public IUser CreateUser(IUser value, string password)
        {
            return CreateUser(value, password, true, null);
        }

        public IUser CreateUser(IUser value, string password, bool activationRequired, int? activationTemplateId)
        {
            value.HashedPassword = password.GetMd5CheckSum();
            value.CreateDate = System.DateTime.Now;
            value.InvalidLogons = 0;
            value.IsApproved = !activationRequired;
            value.LastInvalidLogon = null;
            if (activationRequired)
            {
                SendActivationEmail(value.Email, activationTemplateId);
            }
            return userProvider.AddUser(value);
        }

        private string SendActivationEmail(string email, int? activationTemplateId)
        {
            string activationKey = Guid.NewGuid().ToString().GetMd5CheckSum();
            Dictionary<string, string> parameters = new Dictionary<string, string> { { "email", email }, { "activationKey", activationKey } };
            if (EmailManager.Instance.SendEmail(new System.Net.Mail.MailAddress(email), activationTemplateId, Enums.EmailTemplates.ActivationTemplate, parameters))
            {
                return activationKey;
            }
            else
            {
                throw new Exception(string.Format("Error occured while tying to send email on {0} with parameters {1}, registrtation aborded", email, parameters));
            }
        }

        public IUser UpdateUserProperties(IUser value)
        {
            IUser user = userProvider.GetUser(value.Email);
            if (user != null)
            {
                user.Properties = value.Properties;
                userProvider.UpdateUser(user);
            }
            return value;
        }

        public ValidateUserResult ValidateUser(string email, string password)
        {
            string hashedPassword = password.GetMd5CheckSum();
            var user = userProvider.GetUser(email);
            if (user == null)
            {
                return ValidateUserResult.InvalidEmailOrPassword;
            } else
                if (user.IsLockOut)
                {
                    return ValidateUserResult.Locked;
                } else
                    if (user.HashedPassword != hashedPassword)
                    {
                        if (user.LastInvalidLogon.HasValue && user.LastInvalidLogon.Value.AddMinutes(15) > System.DateTime.Now)
                        {
                            user.InvalidLogons++;
                        }
                        else
                        {
                            user.InvalidLogons = 1;
                        }
                        user.LastInvalidLogon = System.DateTime.Now;
                        userProvider.UpdateUser(user);
                        return ValidateUserResult.InvalidEmailOrPassword;
                    }
                    else
                    {
                        return ValidateUserResult.Validated;
                    }
        }

        public void DeleteUser(int userId)
        {
            userProvider.DeleteUser(userId);
        }

        public IUser ConfirmUser(string email, string activationKey)
        {
            if (string.IsNullOrEmpty(activationKey)) return null;
            var user = userProvider.GetUser(email);
            if (user != null && user.ActivationKey == activationKey)
            {
                user.IsApproved = true;
                user.ActivationKey = null;
                userProvider.UpdateUser(user);
                return user;
            }
            else
            {
                return null;
            }
        }

        public ResetPasswordResult ResetPassword(string email, int? emailTemplateId)
        {
            var user = userProvider.GetUser(email);
            if (user == null) return ResetPasswordResult.emailDoesNotExists;
            else
            {
                if (!user.IsApproved)
                {
                    return ResetPasswordResult.accountNotActivated;
                }
                else
                {
                    string passwordResetKey = Guid.NewGuid().ToString().GetMd5CheckSum();
                    user.PasswordResetKey = passwordResetKey;
                    Dictionary<string, string> parameters = new Dictionary<string, string> { { "email", email }, { "passwordResetKey", passwordResetKey } };
                    try
                    {
                        EmailManager.Instance.SendEmail(new System.Net.Mail.MailAddress(email), emailTemplateId, EmailTemplates.ResetPasswordTemplate, parameters);
                        return ResetPasswordResult.cannotSendEmail;
                    }
                    catch
                    {
                        userProvider.UpdateUser(user);
                        return ResetPasswordResult.resetEmailSent;
                    }
                }
            }
        }

        public IUser SetNewPassword(string newPassword, string activationKey, string email)
        {
            if (string.IsNullOrEmpty(activationKey)) return null;
            var user = userProvider.GetUser(email);
            if (user != null && user.PasswordResetKey == activationKey)
            {
                user.HashedPassword = newPassword.GetMd5CheckSum();
                user.PasswordResetKey = null;
                userProvider.UpdateUser(user);
            }
            return user;
        }


    }
}
